package com.lt.lumentracks.service.Impl;

import com.lt.lumentracks.constant.RedisConstant;
import com.lt.lumentracks.context.BaseContext;
import com.lt.lumentracks.entity.po.ConversationUser;
import com.lt.lumentracks.exception.BaseException;
import com.lt.lumentracks.mapper.ConversationUserMapper;
import com.lt.lumentracks.service.IConversationUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 会话成员表 (关联表) 服务实现类
 * </p>
 *
 * @author swl
 * @since 2025-10-06
 */
@Service
public class ConversationUserServiceImpl extends ServiceImpl<ConversationUserMapper, ConversationUser> implements IConversationUserService {

    @Autowired
    private ConversationUserMapper conversationUserMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final int MAX_UNREAD_COUNT_DEFAULT = 100; // 默认值--最多返回未读消息数


    // 更新用户在某会话中最后阅读的消息id
    @Override
    public void updateLastMsg(Long convId, Long lastMsgIdNew) {

        Integer userId = BaseContext.getCurrentId();

        boolean updateRes = lambdaUpdate().eq(ConversationUser::getConversationId, convId)
                .eq(ConversationUser::getUserId, userId)
                // .and()创建了一个嵌套的条件组，相当于SQL中的括号，等价于 AND (last_read_message_id IS NULL OR last_read_message_id < ?)
                .and(w -> w
                        .isNull(ConversationUser::getLastReadMessageId) // 确保id为null的记录也能成功更新
                        .or()
                        .lt(ConversationUser::getLastReadMessageId, lastMsgIdNew)) // 新ID必须大于旧ID，避免“往后看”的bug，统计未读数的话会变少甚至为负
                .set(ConversationUser::getLastReadMessageId, lastMsgIdNew)
                .update();
        if (!updateRes) {
            throw new BaseException("更新用户最后阅读消息失败");
        }
    }

    // 批量更新用户在某会话中最后阅读的消息id
    @Override
    @Transactional
    public void batchUpdateLastMsg(List<ConversationUser> cu_list) {
        boolean updateRes = conversationUserMapper.updateBatch(cu_list);
        if (!updateRes) {
            throw new BaseException("批量更新用户最后阅读消息失败");
        }
    }

    /** 更新用户在某会话中最后阅读的消息id -- 存入redis中
     * @param convId 会话id
     * @param lastMsgIdNew 新消息id
     */
    @Override
    public void updateLastMsg_V2(Long convId, Long lastMsgIdNew) {
        Integer userId = BaseContext.getCurrentId();
        String key = RedisConstant.userLastReadMsgKey(userId, convId);
        redisTemplate.opsForValue().set(key, lastMsgIdNew.toString(), Duration.ofSeconds(30));
    }


    // 两个用户之间是否已经存在单聊会话
    @Override
    public boolean isSingleChatExists(Integer senderId, Integer receiverId) {
        return conversationUserMapper.isSingleChatExists(senderId, receiverId) > 0;
    }

    // 获取两个用户之间的单聊会话id
    @Override
    public List<Long> getSingleChat(Integer currentId, Integer talkerUid) {
        List<Long> singleChat = conversationUserMapper.getSingleChat(currentId, talkerUid);
        return Objects.requireNonNullElseGet(singleChat, List::of); // 避免返回null
    }

    /** 批量查询（对于当前用户来说的）每个会话的未读消息数
     * @param rawIds 会话id集合
     * @param userId 当前用户id
     * @param maxReturnCount 最多返回的未读数
     * @return 存储Map对象的List集合，其中key为会话ID，value为未读消息数
     */
    @Override
    public List<Map<String, Object>> countUnreadMessages(List<Long> rawIds, Integer userId, int maxReturnCount) {
        if (rawIds == null || rawIds.isEmpty()) {
            return List.of();
        }
        return conversationUserMapper.countUnreadMessages(rawIds, userId, maxReturnCount);
    }

    // 重载方法：当不传maxReturnCount时，默认设置为100
    @Override
    public List<Map<String, Object>> countUnreadMessages(List<Long> rawIds, Integer userId) {
        return countUnreadMessages(rawIds, userId, MAX_UNREAD_COUNT_DEFAULT); // 调用原方法，并传入默认值100
    }

    /** 查询用户在当前会话中上次阅读的消息id
     * @param convId 会话id
     * @return 上次阅读的消息id
     */
    @Override
    public Long queryLastMsg(Long convId) {
        Integer userId = BaseContext.getCurrentId();
        ConversationUser one = lambdaQuery()
                .eq(ConversationUser::getUserId, userId)
                .eq(ConversationUser::getConversationId, convId)
                .select(ConversationUser::getLastReadMessageId)
                .one();
        if (one == null) {
            return null;
        }
        return one.getLastReadMessageId();
    }
}
